﻿using System.Collections.Generic;
using System.Xml.Linq;

namespace XSerialization.Generator
{
    public interface IXsdType
    {
        /// <summary>
        /// Modified Class/Interface/Enum Name
        /// </summary>
        string Name { get; set; }

        /// <summary>
        /// Original Xml Name
        /// </summary>
        string XmlName { get; set; }

        /// <summary>
        /// Reference to the original XSD Node
        /// </summary>
        XElement XsdNode { get; set; }

        /// <summary>
        /// Summary Data
        /// </summary>
        string Description { get; set; }
    }

    /// <summary>
    /// Base Class for all XSD Types
    /// </summary>
    public abstract class XsdType : IXsdType
    {
        private string _name;

        /// <summary>
        /// Modified Class/Interface/Enum Name
        /// </summary>
        public string Name
        {
            get { return _name; }
            set
            {
                _name = ConvertUtilities.ConvertXsdName(value);
            }
        }

        /// <summary>
        /// Original Xml Name
        /// </summary>
        public string XmlName { get; set; }

        /// <summary>
        /// Reference to the original XSD Node
        /// </summary>
        public XElement XsdNode { get; set; }

        /// <summary>
        /// Summary Data
        /// </summary>
        public string Description { get; set; }

        /// <summary>
        /// Ctor
        /// </summary>
        /// <param name="name">Xsd Name</param>
        protected XsdType(string name) : this(name, null, string.Empty) { }

        /// <summary>
        /// Ctor
        /// </summary>
        /// <param name="name">Xsd Name</param>
        /// <param name="xsdNode">Xsd Node</param>
        protected XsdType(string name, XElement xsdNode)  : this(name, xsdNode, string.Empty) { }

        /// <summary>
        /// Ctor
        /// </summary>
        /// <param name="name">Type Name</param>
        /// <param name="xsdNode">Type Node</param>
        /// <param name="description">Type Description</param>
        protected XsdType(string name, XElement xsdNode, string description)
        {
            XmlName = name;
            Name = name;
            XsdNode = xsdNode;
            Description = description;

            //T4 Templates throw exception if description is null
            if (Description == null) Description = string.Empty;
        }
    }

    /// <summary>
    /// Enum
    /// </summary>
    public class XsdEnumerationType : XsdType
    {
        /// <summary>
        /// List of all Enumerations
        /// </summary>
        public IList<string> Enumerations { get; set; }

        /// <summary>
        /// Ctor
        /// </summary>
        /// <param name="name">Type Name</param>
        /// <param name="node">Type Node</param>
        public XsdEnumerationType(string name, XElement node) : base(name, node)
        {
            Enumerations = new List<string>();
        }
    }

    /// <summary>
    /// Primitive C# Type
    /// </summary>
    public class XsdSimpleType : XsdType
    {
        /// <summary>
        /// C# Type Name
        /// </summary>
        public string TypeName { get; set; }

        /// <summary>
        /// Ctor
        /// </summary>
        /// <param name="name">Type Name</param>
        /// <param name="node">Type Node</param>
        public XsdSimpleType(string name, XElement node) : base(name, node) { }
    }

    /// <summary>
    /// Class or Interface
    /// </summary>
    public class XsdComplexType : XsdType
    {
        /// <summary>
        /// Interface Name
        /// </summary>
        public string InterfaceName
        {
            get { return "I" + Name; }
        }

        /// <summary>
        /// List of all defined Properties
        /// </summary>
        public IDictionary<string, IXsdTypeReference> Properties { get; set; }

        /// <summary>
        /// Ctor
        /// </summary>
        /// <param name="name">Type Name</param>
        /// <param name="node">Type Node</param>
        /// <param name="description">Type Description</param>
        public XsdComplexType(string name, XElement node, string description) : base(name, node, description)
        {
            Properties = new Dictionary<string, IXsdTypeReference>();
        }
    }
}
